import ctypes
import inspect
import os
import configparser
import sys
import threading
import time
import traceback

from selenium.common.exceptions import TimeoutException
from selenium.webdriver.chrome.options import Options
from selenium import webdriver
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.wait import WebDriverWait

driver = None
g_acc = None
g_pwd = None
g_arr_lesson_url = []
g_thread1 = None


def working():
    init()
    login()
    init_ke_cheng()
    start_read_lesson()
    # driver.close()


def init():
    # global driver
    # p = r"C:\Users\Administrator\AppData\Roaming\Mozilla\Firefox\Profiles\vl7nl0b6.default"
    # profile = webdriver.FirefoxProfile(p)
    # profile.set_preference("plugin.state.flash", 2)
    # driver = webdriver.Firefox(profile)

    # 创建Chrome浏览器的一个Options实例对象
    chrome_options = Options()
    # 设置Chrome浏览器禁用PDF和Flash插件,把图片也关掉了。
    profile = {"profile.default_content_setting_values.plugins": 1,
               "profile.content_settings.plugin_whitelist.adobe-flash-player": 1,
               "profile.content_settings.exceptions.plugins.*,*.per_resource.adobe-flash-player": 1,
               "credentials_enable_service": False,
               "profile.password_manager_enabled": False}

    chrome_options.add_experimental_option("prefs", profile)
    # 向Options实例中添加禁用扩展插件的设置参数项
    chrome_options.add_argument("--disable-extensions")
    # 添加屏蔽--ignore-certificate-errors提示信息的设置参数项
    chrome_options.add_experimental_option("excludeSwitches", ["ignore-certificate-errors"])
    # 添加浏览器最大化的设置参数项，启动同时最大化窗口
    chrome_options.add_argument('--start-maximized')
    chrome_options.add_argument("--user-data-dir=" + r"C:/Users/Administrator/AppData/Local/Google/Chrome/User Data/")
    # 启动带有自定义设置的Chrome浏览器
    global driver
    driver = webdriver.Chrome(chrome_options=chrome_options)
    driver.implicitly_wait(10)

    global g_acc, g_pwd
    g_acc = get_config('login', 'acc')
    g_pwd = get_config('login', 'pwd')


def login():
    driver.get("http://www.ca163.net/ca163/hyper/login")
    driver.implicitly_wait(5)
    try:
        elem = driver.find_element_by_name("spad")
        elem.clear()
        elem.send_keys(g_acc)

        elem = driver.find_element_by_name("aces")
        elem.clear()
        elem.send_keys(g_pwd)

        # time.sleep(15)

        WebDriverWait(driver, 60 * 1).until(
            EC.presence_of_element_located((By.CLASS_NAME, 'cont-adv'))
        )
    except Exception as ex:
        pass
    # xxx 这里应该是在点击登录后，自动操作
    # driver.implicitly_wait(10)
    # driver.find_element_by_id("btn-login").click()


def init_ke_cheng():
    # driver.get("http://www.ca163.net/ca163/authc/myCourse?state=1")
    # 获得这里有几个分页
    page_url = "http://www.ca163.net/ca163/authc/myCourse?state=1"
    driver.get(page_url)
    driver.implicitly_wait(10)

    last_page_number = "1"
    try:
        last_page_elem = driver.find_element_by_xpath('//div[@id="reply-pagination"]/div/a[last()]')
        last_page_number = last_page_elem.get_attribute('data-current')
    except Exception as ex:
        pass

    for i in range(int(last_page_number)):
        driver.get(page_url + "&page=" + str(i + 1))

        # 获得这一页有哪些项目是未完成的
        need_start_elems = driver.find_elements_by_xpath('//a[@class="mycourse-green"][contains(text(), "进入课程")]')
        [g_arr_lesson_url.append(elm.get_property('href')) for elm in need_start_elems]


def start_read_lesson():
    arr_class = []
    for i in g_arr_lesson_url:
        driver.get(i)
        weiwancheng_elems = driver.find_elements_by_xpath('//span[contains(text(),"未完成")]/following::span/a')
        [arr_class.append(elm.get_property('href')) for elm in weiwancheng_elems]

        weiakaishi_elems = driver.find_elements_by_xpath('//span[contains(text(),"未开始")]/following::span/a')
        [arr_class.append(elm.get_property('href')) for elm in weiakaishi_elems]

    start_read_class(arr_class)


def start_read_class(arr_class):
    global g_thread1
    chk_elm_xpath = '//td[@class="learnpercent"]/span/span'
    for i, item in enumerate(arr_class):
        # if g_thread1:
        #     stop_thread(g_thread1)
        driver.get(item)
        print('第' + str(i + 1) + '课')

        is_all_right = False
        try_count = 0
        while not is_all_right and try_count < 5:
            # g_thread1 = threading.Thread(target=chk_timu, daemon=True)
            # g_thread1.start()
            # 检查进度是否出现了，出现就继续播放，不出现就刷新页面
            try:
                # 网页有bug？右上角不显示进度条，学习无效，这里判断一下是否出现进度
                WebDriverWait(driver, 30).until(
                    EC.visibility_of_element_located((By.XPATH, chk_elm_xpath))
                )

                driver.find_element_by_xpath(chk_elm_xpath)
                is_all_right = True

                # WebDriverWait(driver, 40 * 60).until(
                #     EC.visibility_of_element_located((By.ID, 'dd'))
                # )

                WebDriverWait(driver, 40 * 60).until(
                    EC.text_to_be_present_in_element((By.XPATH, chk_elm_xpath), '已完成')
                    # EC.presence_of_element_located((By.XPATH, '//td[@class="learnpercent"]/span/span'))
                )
            except (TimeoutException, Exception) as ex:
                # stop_thread(g_thread1)
                writeErrToLog()
                try_count = try_count + 1
                if try_count > 5:
                    raise ex
                print('重试第' + str(try_count) + '次')
                driver.refresh()


def chk_timu():
    try:
        while True:
            WebDriverWait(driver, 40 * 60).until(
                EC.visibility_of_element_located((By.ID, 'dd'))
            )
            # 如果dd出现了，说明题目出现了，先选中一个答案
            xuanze_elems = driver.find_elements_by_xpath('//input[@name="danxuan"]')
            if len(xuanze_elems) > 0:
                xuanze_elems[0].click()

            # 点击提交答案
            btnTiJiao_elem = driver.find_element_by_xpath('//a[@class="reply-sub"]')
            btnTiJiao_elem.click()

            # 如果选错，则在弹出提示的时候按确定

            btnQueDing_elem = driver.find_element_by_xpath('//a[@class="l-btn l-btn-small"]')
            btnQueDing_elem.click()

            time.sleep(3)

    except Exception as ex:
        global g_thread1
        stop_thread(g_thread1)
        writeErrToLog()
        print('线程异常：' + traceback.print_exc())


def get_config(section, key):
    config = configparser.ConfigParser()
    path = os.path.split(os.path.realpath(__file__))[0] + '/config.conf'
    config.read(path)
    return config.get(section, key)


def writeErrToLog():
    traceback.print_exc(file=open('err.txt', 'w+'))


def _async_raise(tid, exctype):
    """raises the exception, performs cleanup if needed"""
    tid = ctypes.c_long(tid)
    if not inspect.isclass(exctype):
        exctype = type(exctype)
    res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(exctype))
    if res == 0:
        raise ValueError("invalid thread id")
    elif res != 1:
        # """if it returns a number greater than one, you're in trouble,
        # and you should call it again with exc=NULL to revert the effect"""
        ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, None)
        raise SystemError("PyThreadState_SetAsyncExc failed")


def stop_thread(thread):
    _async_raise(thread.ident, SystemExit)



if __name__ == "__main__":
    working()
